/**
 * @file    gt98xx_drv_iwdt.c
 * @author  Giantec-Semi ATE
 * @brief   Source file of IWDT driver module.
 * @version 0.1
 * 
 * @copyright Copyright (c) 2021 Giantec-Semi
 */
#include "gt98xx_drv_iwdt.h"

/**
 * @addtogroup GT98xx_DRV
 * @{
 */

/**
 * @addtogroup IWDT_DRV
 * @{
 */

/**
 * @addtogroup IWDT_DRV_Private_Macros
 * @{
 */

/**
 * @def IS_DRV_IWDT_TIMEOUT
 * @brief Check if __VALUE__ is IWDT Time out type
 */
#define IS_DRV_IWDT_TIMEOUT(__VALUE__)      (((__VALUE__) == DRV_IWDT_TIMEOUT_16) \
                                            || ((__VALUE__) == DRV_IWDT_TIMEOUT_32) \
                                            || ((__VALUE__) == DRV_IWDT_TIMEOUT_64) \
                                            || ((__VALUE__) == DRV_IWDT_TIMEOUT_128) \
                                            || ((__VALUE__) == DRV_IWDT_TIMEOUT_256) \
                                            || ((__VALUE__) == DRV_IWDT_TIMEOUT_512) \
                                            || ((__VALUE__) == DRV_IWDT_TIMEOUT_1k))
                                            
/**
 * @def IS_DRV_IWDT_DIVISOR
 * @brief Check if __VALUE__ is IWDT Divisor type
 */
#define IS_DRV_IWDT_DIVISOR(__VALUE__)      (((__VALUE__) == DRV_IWDT_PRESCALER_2) \
                                            || ((__VALUE__) == DRV_IWDT_PRESCALER_4) \
                                            || ((__VALUE__) == DRV_IWDT_PRESCALER_8) \
                                            || ((__VALUE__) == DRV_IWDT_PRESCALER_16) \
                                            || ((__VALUE__) == DRV_IWDT_PRESCALER_32) \
                                            || ((__VALUE__) == DRV_IWDT_PRESCALER_64) \
                                            || ((__VALUE__) == DRV_IWDT_PRESCALER_128) \
                                            || ((__VALUE__) == DRV_IWDT_PRESCALER_256))
                                            

/**
 * @def IS_DRV_IWDT_ACTION
 * @brief Check if __VALUE__ is IWDT Action type
 */
#define IS_DRV_IWDT_ACTION(__VALUE__)       (((__VALUE__) == DRV_IWDT_Action_RST) \
                                            || ((__VALUE__) == DRV_IWDT_Action_IT))
                                            
/** @} IWDT_DRV_Private_Macros */


/**
 * @addtogroup IWDT_DRV_Exported_Functions
 * @{
 */

/**
 * @fn ErrorStatus DrvIwdtDeInit(IwdtTypedef* iwdt_instance)
 * @brief De-initialize IWDT registers
 * 
 * @param[in] iwdt_instance IWDT instance
 * @return An ErrorStatus enumeration value
 * @retval kSuccess IWDT registers are de-initialized
 * @retval kError IWDT registers are not de-initialized
 */
ErrorStatus DrvIwdtDeInit(IwdtTypedef* iwdt_instance) {
  ErrorStatus status = kSuccess;
  /* Check the IIWDT Instance IWDTx */
  assert_param(IS_IWDT_INSTANCE(iwdt_instance));
  if (IWDT == iwdt_instance)
  {
    CLEAR_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_IWDT);
    SET_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_IWDT);
  }
  else
  {
    status = kError;
  }
  return status;
}

/**
 * @fn ErrorStatus DrvIwdtInit(IwdtTypedef* iwdt_instance, DrvIwdtInitTypedef* iwdt_init_struct)
 * @brief Initialize IWDT registers according to the specified parameters in @ref DrvIwdtInitTypedef
 * 
 * @param[in] iwdt_instance IWDT instance
 * @param[in] iwdt_init_struct pointer to a @ref DrvIwdtInitTypedef structure that
 *            contians the configuration information for the specified IWDT peripheral
 * @return An ErrorStatus enumeration value
 * @retval kSuccess IWDT registers are de-initialized
 * @retval kError IWDT registers are not de-initialized
 */
ErrorStatus DrvIwdtInit(IwdtTypedef* iwdt_instance, DrvIwdtInitTypedef* iwdt_init_struct) {
  ErrorStatus status = kError;
  /* Check the IIWDT Instance IWDTx */
  assert_param(IS_IWDT_INSTANCE(uart_instance));
  assert_param(IS_DRV_IWDT_TIMEOUT(iwdt_init_struct->time_out));
  assert_param(IS_DRV_IWDT_ACTION(iwdt_init_struct->action));
  assert_param(IS_DRV_IWDT_DIVISOR(iwdt_init_struct->divisor));
  
  if (!DrvIwdtIsEnabled(iwdt_instance))
  {
    DrvIwdtSetCounterValue(iwdt_instance, iwdt_init_struct->load_value);
    
    MODIFY_REG(iwdt_instance->TCR,
              (IWDT_TCR_TIMEOUT_RANGE | IWDT_TCR_ACTION | IWDT_TCR_DIVISOR),
              (iwdt_init_struct->time_out | iwdt_init_struct->action | iwdt_init_struct->divisor));
    
    status = kSuccess;
    
  }
  
  return status;
}

/**
 * @fn void DrvIwdtStructInit(DrvIwdtInitTypedef* iwdt_init_struct, uint32_t value)
 * @brief Set each @ref DrvIwdtInitTypedef field to default value
 * 
 * @param[out] iwdt_init_struct pointer to a @ref DrvIwdtInitTypedef structure
 *             whose field will be set to default values
 * @param[in]  value iwdt value
 * @return None
 */
void DrvIwdtStructInit(DrvIwdtInitTypedef* iwdt_init_struct, uint32_t value) {
  iwdt_init_struct->load_value      = value;
  iwdt_init_struct->time_out        = DRV_IWDT_TIMEOUT_16;
  iwdt_init_struct->action          = DRV_IWDT_ACTION_IT;
  iwdt_init_struct->divisor         = DRV_IWDT_PRESCALER_2;
}
/** @} IWDT_DRV_Exported_Functions */
/** @} IWDT_DRV */
/** @} GT98xx_DRV */
